package com.gitee.magic.framework.base.rest;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import com.gitee.magic.context.ConverterEditorUtils;
import com.gitee.magic.core.json.JsonArray;
import com.gitee.magic.core.utils.reflect.TypeReference;
import com.gitee.magic.framework.head.vo.BaseVO;
import com.gitee.magic.framework.head.vo.ListVO;
import com.gitee.magic.framework.head.vo.ObjectVO;
import com.gitee.magic.framework.head.vo.PageVO;
import com.gitee.magic.framework.head.vo.QueryVO;

/**
 * @author start
 */
public class ApiRestDecoder {

	public Object decode(String responseContent, Type type) {
		if(type instanceof ParameterizedType) {
			Class<?> prototype=(Class<?>) ((ParameterizedType) type).getRawType();
			if (prototype.equals(ObjectVO.class)||
					prototype.equals(ListVO.class)||
					prototype.equals(PageVO.class)) {
				Type responsePrototype = ((ParameterizedType) type).getActualTypeArguments()[0];
				if (prototype.equals(ObjectVO.class)) {
					return forObject(responseContent, (Class<?>)responsePrototype);
				}else if (prototype.equals(ListVO.class)) {
					return forList(responseContent, (Class<?>)responsePrototype);
				}else if (prototype.equals(PageVO.class)) {
					return forPage(responseContent, (Class<?>)responsePrototype);
				}
			}
			return ConverterEditorUtils.restoreObject(prototype, responseContent);
		}else {
			Class<?> prototype=(Class<?>)type;
			if (prototype.equals(BaseVO.class)) {
				return forBase(responseContent);
			}else if (prototype.equals(List.class)) {
				return forList(responseContent, prototype).getData();
			}else if (prototype.equals(QueryVO.class)) {
				PageVO<?> page = forPage(responseContent, prototype);
				return new QueryVO<>(page.getData(), page.getTotal());
			}else {
				return forObject(responseContent, prototype).getData();
			}
		}
	}
	
	public Object decodeExt(String responseContent, Type type) {
		Class<?> prototype=(Class<?>)type;
		if (prototype.equals(List.class)) {
			return ConverterEditorUtils.restoreList(prototype, new JsonArray(responseContent));
		}else if (prototype.equals(QueryVO.class)) {
			TypeReference<QueryVO<?>> typeReference = new TypeReference<QueryVO<?>>(prototype) {};
			return ConverterEditorUtils.restoreObject(prototype, responseContent,typeReference);
		}else {
			return ConverterEditorUtils.restoreObject(prototype, responseContent);
		}
	}

	public BaseVO forBase(String responseContent) {
		ResponseResolve resolve = new ResponseResolve(responseContent);
		BaseVO response = resolve.analysis(BaseVO.class);
		resolve.checkResponse(response);
		return response;
	}

	public <R>ObjectVO<R> forObject(String responseContent, Class<R> responsePrototype) {
		TypeReference<ObjectVO<R>> typeReference = new TypeReference<ObjectVO<R>>(responsePrototype) {};
		ResponseResolve resolve = new ResponseResolve(responseContent);
		ObjectVO<R> response = resolve.analysis(ObjectVO.class, typeReference);
		resolve.checkResponse(response);
		return response;
	}

	public <R>ListVO<R> forList(String responseContent, Class<R> responsePrototype) {
		TypeReference<ListVO<R>> typeReference = new TypeReference<ListVO<R>>(responsePrototype) {};
		ResponseResolve resolve = new ResponseResolve(responseContent);
		ListVO<R> response = resolve.analysis(ListVO.class, typeReference);
		resolve.checkResponse(response);
		return response;
	}

	public <R>PageVO<R> forPage(String responseContent, Class<R> responsePrototype) {
		TypeReference<PageVO<R>> typeReference = new TypeReference<PageVO<R>>(responsePrototype) {};
		ResponseResolve resolve = new ResponseResolve(responseContent);
		PageVO<R> response = resolve.analysis(PageVO.class, typeReference);
		resolve.checkResponse(response);
		return response;
	}

}
